/*++

Copyright (c) 1989 - 1999 Microsoft Corporation

Module Name:

    mrxglobs.h

Abstract:

    The global include file for HWFS mini-redirector

--*/

#pragma once

#include "../../viofs/shared/virtiofs.h"
#include "../../viofs/shared/virtiofs_kernel.h"

#define HWFS_POOLTAG               'HWFS'

#define FUSE_CACHE_MAX_ELEMENTS 4096
#define FUSE_CACHE_TTL (30 * 1000000000ULL) // in nanoseconds

/** Flags for HWFS share folder
*   values 0 and 1 are reserved as ATTR_SUBMOUNT and ATTR_DAX
*/
#define HWFS_SHARE_FLAG_READ_ONLY           (1 << 2)
#define HWFS_SHARE_FLAG_CASE_INSENSITIVE    (1 << 3)

typedef struct FUSE_CACHE FUSE_CACHE, *PFUSE_CACHE, **PPFUSE_CACHE;


typedef UINT64 HWFS_HANDLE, * PHWFS_HANDLE;
typedef struct HWFS_FILE_ {
    UINT32   ShareId;
    UINT32   IsValid;
    UINT64   ShareGeneration;
    UINT64   FuseNodeId;
    UINT64   FuseHandle;
    PCHAR    Utf8FileName;
    BOOLEAN  IsDir;

    BOOLEAN  DeleteOnClose;       // DELETE_ON_CLOSE from SetDisposition
    BOOLEAN  ForcedDeleteOnClose; // DELETE_ON_CLOSE from file-open
} HWFS_FILE, *PHWFS_FILE;

typedef struct _HWFS_VOLUME_INFO_ {
    UINT64  BytesTotal; // Total bytes on system
    UINT64  BytesFree;  // Bytes free (without user quota)
    UINT64  BytesAvail; // Bytes available to current user
    BOOLEAN IsReadOnly;
    BOOLEAN IsCaseInsensitive;
    UINT64  UpdateTs; // timestamp (100ns) when VolumeInfo was updated
} HWFS_VOLUME_INFO, *PHWFS_VOLUME_INFO;

typedef struct HWFS_SHARE_ {
    UINT32   ShareId;
#define HWFS_SHARE_STATE_ALLOCATED (1u << 0)
#define HWFS_SHARE_STATE_CONNECTED (1u << 1)
    UINT32   ShareState;
    UINT64   ShareGeneration; // used to track that SrvOpen conforms Share
    UINT64   RootId;
    UINT64   FuseGeneration;
    FAST_MUTEX       ReconnectMutex;
    UNICODE_STRING   ShareName;
    HWFS_VOLUME_INFO VolInfo;
    PFUSE_CACHE      FuseEntryCache;
} HWFS_SHARE, *PHWFS_SHARE;

#define HWFS_INVALID_HANDLE 0ull

#define HWFS_WELLKNOWN_BASE (1ull << 63)
#define HWFS_ROOT_HANDLE    (HWFS_WELLKNOWN_BASE + 0)

typedef struct _HWFS_FILE_INFO {
    FILE_BASIC_INFORMATION     BasicInfo;
    FILE_STANDARD_INFORMATION  StandardInfo;
} HWFS_FILE_INFO, *PHWFS_FILE_INFO;

extern PRDBSS_DEVICE_OBJECT g_hwFsDeviceObject;

// The following enum type defines the various states associated with the null
// mini redirector. This is used during initialization

typedef enum _HWFS_STATE_ {
    HWFS_STARTABLE,
    HWFS_START_IN_PROGRESS,
    HWFS_STARTED
} HWFS_STATE;

extern HWFS_STATE   g_hwFsState;

//
//  Use the RxDefineObj and RxCheckObj macros
//  to enforce signed structs.
//

#define RxDefineObj(type, var)            \
        (var).Signature = type##_SIGNATURE

#define RxCheckObj(type, var)             \
        ASSERT((var).Signature == type##_SIGNATURE)

//
//  Use the RxDefineNode and RxCheckNode macros
//  to enforce node signatures and sizes.
//

#define RxDefineNode(node, type)          \
        (node)->NodeTypeCode = NTC_##type;    \
        (node)->NodeByteSize = sizeof(type)

#define RxCheckNode(node, type)           \
        ASSERT(NodeType(node) == NTC_##type)

//
// struct node types - start from 0xFF00
//
typedef enum _HWFS_STORAGE_TYPE_CODES {
    NTC_HWFS_DEVICE_EXTENSION      =   (NODE_TYPE_CODE)0xFF00,
    NTC_HWFS_SRVCALL_EXTENSION     =   (NODE_TYPE_CODE)0xFF01,
    NTC_HWFS_NETROOT_EXTENSION     =   (NODE_TYPE_CODE)0xFF02,
    NTC_HWFS_FCB_EXTENSION         =   (NODE_TYPE_CODE)0xFF03,
    NTC_HWFS_FOBX_EXTENSION        =   (NODE_TYPE_CODE)0xFF04,
    NTC_HWFS_SRVOPEN_EXTENSION     =   (NODE_TYPE_CODE)0xFF05,
} HWFS_STORAGE_TYPE_CODES;

//
// typedef our device extension - stores state global to the driver
//
typedef struct _HWFS_DEVICE_EXTENSION {
    // Node Type and Size
    NODE_TYPE_CODE          NodeTypeCode;
    NODE_BYTE_SIZE          NodeByteSize;

    // Owning device object
    PRDBSS_DEVICE_OBJECT    DeviceObject;

    //  Num of active nodes
    ULONG                   ActiveNodes;

    // List of local connections
    LIST_ENTRY              ConnectionList;
    FAST_MUTEX              LCMutex;

    PDEVICE_OBJECT          ViofsDeviceObject;
    PFILE_OBJECT            ViofsFileObject;

    PVOID                    ViofsContext;
    PVIRTIOFS_INKERNEL_FUSE_REQUEST_ROUTINE_FUNC  ViofsSubmitRequest;
    PVIRTIOFS_INKERNEL_FUSE_CANCEL_REQUEST_FUNC   ViofsCancelRequest;
    PVIRTIOFS_INKERNEL_RESET_FUNC                 ViofsResetDevice;

    // Write request must not exceed this value
    UINT32                   FuseMaxWrite;
    UINT32                   FuseMaxPages;

    LARGE_INTEGER            FuseTimeout;
    PLARGE_INTEGER           FuseTimeoutPtr;

    BOOLEAN                  FuseSessionInitialized;
} HWFS_DEVICE_EXTENSION, *PHWFS_DEVICE_EXTENSION;

//
// typedef our srv-call extension - stores state global to a node
// NYI since wrapper does not allocate space for this..........!
//
typedef struct _HWFS_SRVCALL_EXTENSION {
    //
    //  Node type code and size
    //
    NODE_TYPE_CODE          NodeTypeCode;
    NODE_BYTE_SIZE          NodeByteSize;
} HWFS_SRVCALL_EXTENSION, *PHWFS_SRVCALL_EXTENSION;

//
// NET_ROOT extension - stores state global to a root
//
typedef struct _HWFS_NETROOT_EXTENSION {
    //
    //  Node type code and size
    //
    NODE_TYPE_CODE          NodeTypeCode;
    NODE_BYTE_SIZE          NodeByteSize;

    UNICODE_STRING          RootName;

    BOOLEAN                 fInitialized;

    HWFS_SHARE              Share;
} HWFS_NETROOT_EXTENSION, *PHWFS_NETROOT_EXTENSION;

//
//  FCB = File Control Block. For one FCB there could be several FOBX, reffering to the same file
//

typedef struct _HWFS_FCB_EXTENSION {
    //
    //  Node type code and size
    //
    NODE_TYPE_CODE          NodeTypeCode;
    NODE_BYTE_SIZE          NodeByteSize;

    HWFS_FILE_INFO          FileInfo;

    UINT64                  WriteOnlyOpenCnt;
    UINT64                  WriteOpenCnt;
} HWFS_FCB_EXTENSION, *PHWFS_FCB_EXTENSION;

#define HWFS_FOBX_DIRINFO_SIZE  (8 * 4096)

typedef struct _HWFS_FOBX_EXTENSION {
    //
    //  Node type code and size
    //
    NODE_TYPE_CODE          NodeTypeCode;
    NODE_BYTE_SIZE          NodeByteSize;

    //
    // We use FOBX_EXTENSION mostly while HwFsQueryDirectory.
    //

    // Template is always valid after search initialization.
    // We use local 32bytes buffer to avoid memory-allocations if possible
#define HWFS_FOBX_SMALLBUF_SIZE  32
#define HWFS_FOBX_UNICODE_SMALLBUF_SIZE  64
#define HWFS_FOBX_CONVERTATION_BUF_SIZE  256
    PWCHAR                  ConvertationBuf; // Buffer for converting UTF8 to Unicode
    ANSI_STRING             DirInfoTemplate; // UTF8
    CHAR                    DirInfoSmallTemplateBuf[HWFS_FOBX_SMALLBUF_SIZE];

    UNICODE_STRING          UnicodeDirInfoTemplate;
    CHAR                    UnicodeDirInfoSmallTemplateBuf[HWFS_FOBX_UNICODE_SMALLBUF_SIZE];

    BOOLEAN                 WildcardTemplate; // True if template contains wildcards

    PUCHAR                  Data;
    ULONG                   DataSize;

    UINT64                  DirInfoSize;    // size of valid data in DirInfo

    // Index of file in the CurrDirEntryPtr
    ULONG                   CurrFileIndex;
    PUCHAR                  CurrDirEntryPtr;

    // Offset of the DirEntryPlus for the next direntry
    UINT64                  NextDirentryOffset;

    ULONG                   StartSearchIndex;
} HWFS_FOBX_EXTENSION, * PHWFS_FOBX_EXTENSION;

typedef struct _HWFS_SRVOPEN_EXTENSION {
    //
    //  Node type code and size
    //
    NODE_TYPE_CODE          NodeTypeCode;
    NODE_BYTE_SIZE          NodeByteSize;

    HWFS_FILE               HwfsFile;
    BOOLEAN                 IsReadAccess;
    BOOLEAN                 IsWriteAccess;
} HWFS_SRVOPEN_EXTENSION, * PHWFS_SRVOPEN_EXTENSION;

//
// Structure with establish mapping
//
typedef struct HWFS_CONNECTION_ {
    LIST_ENTRY      Link;
    UNICODE_STRING  RdrName;
    UNICODE_STRING  LocalName;
    UNICODE_STRING  RemoteName;
    UNICODE_STRING  FolderName;
} HWFS_CONNECTION, * PHWFS_CONNECTION;


typedef struct _FUSE_CONTEXT {
    PHWFS_DEVICE_EXTENSION  pDevExt;
    PHWFS_SHARE             pShare;
} FUSE_CONTEXT, *PFUSE_CONTEXT;


//
//  Macros to get & validate extensions
//

#define HWFS_GET_DEVICE_EXTENSION(RxContext)        \
        ((PHWFS_DEVICE_EXTENSION)((PUCHAR)((RxContext)->RxDeviceObject) + sizeof(RDBSS_DEVICE_OBJECT)))

#define HWFS_GET_SRVCALL_EXTENSION(pSrvCall)       \
        (((pSrvCall) == NULL) ? NULL : (PHWFS_SRVCALL_EXTENSION)((pSrvCall)->Context))

#define HWFS_GET_NETROOT_EXTENSION(pNetRoot)        \
        (((pNetRoot) == NULL) ? NULL : (PHWFS_NETROOT_EXTENSION)((pNetRoot)->Context))

#define HWFS_GET_FCB_EXTENSION(pFcb)                \
        (((pFcb) == NULL) ? NULL : (PHWFS_FCB_EXTENSION)((pFcb)->Context))

//
// forward declarations for all dispatch vector methods.
//

extern NTSTATUS
HwFsStart(
    IN OUT struct _RX_CONTEXT * RxContext,
    IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject);

extern NTSTATUS
HwFsStop(
    IN OUT struct _RX_CONTEXT * RxContext,
    IN OUT PRDBSS_DEVICE_OBJECT RxDeviceObject);

extern NTSTATUS
HwFsMinirdrControl(
    IN OUT PRX_CONTEXT RxContext,
    IN OUT PVOID pContext,
    IN OUT PUCHAR SharedBuffer,
    IN     ULONG InputBufferLength,
    IN     ULONG OutputBufferLength,
    OUT PULONG CopyBackLength);

extern NTSTATUS
HwFsDevFcb(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsDevFcbXXXControlFile(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCreate(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCollapseOpen(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsShouldTryToCollapseThisOpen(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsRead(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsWrite(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsLocks(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsFlush(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsFsCtl(
    IN OUT PRX_CONTEXT RxContext);

NTSTATUS
HwFsIoCtl(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsNotifyChangeDirectory(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsComputeNewBufferingState(
    IN OUT PMRX_SRV_OPEN pSrvOpen,
    IN     PVOID         pMRxContext,
    OUT    ULONG         *pNewBufferingState);

extern NTSTATUS
HwFsFlush(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCloseWithDelete(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCleanupFobx(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCloseSrvOpen(
    IN OUT PRX_CONTEXT RxContext
    );

extern NTSTATUS
HwFsClosedSrvOpenTimeOut(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsQueryDirectory(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsQueryEaInformation(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsSetEaInformation(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsQuerySecurityInformation(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsSetSecurityInformation(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsQueryVolumeInformation(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsIsValidDirectory(
    IN OUT PRX_CONTEXT     RxContext,
    IN     PUNICODE_STRING DirectoryName);

extern NTSTATUS
HwFsSetVolumeInformation(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsLowIOSubmit(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCreateVNetRoot(
    IN OUT PMRX_CREATENETROOT_CONTEXT pContext);

extern NTSTATUS
HwFsFinalizeVNetRoot(
    IN OUT PMRX_V_NET_ROOT pVirtualNetRoot,
    IN     PBOOLEAN    ForceDisconnect);

extern NTSTATUS
HwFsFinalizeNetRoot(
    IN OUT PMRX_NET_ROOT pNetRoot,
    IN     PBOOLEAN      ForceDisconnect);

extern NTSTATUS
HwFsUpdateNetRootState(
    IN  PMRX_NET_ROOT pNetRoot);

extern VOID
HwFsExtractNetRootName(
    IN PUNICODE_STRING  FilePathName,
    IN PMRX_SRV_CALL    SrvCall,
    OUT PUNICODE_STRING NetRootName,
    OUT PUNICODE_STRING RestOfName OPTIONAL);

extern NTSTATUS
HwFsCreateSrvCall(
    PMRX_SRV_CALL                  pSrvCall,
    PMRX_SRVCALL_CALLBACK_CONTEXT  pCallbackContext);

extern NTSTATUS
HwFsFinalizeSrvCall(
    PMRX_SRV_CALL    pSrvCall,
    BOOLEAN          Force);

extern NTSTATUS
HwFsSrvCallWinnerNotify(
    IN OUT PMRX_SRV_CALL  pSrvCall,
    IN     BOOLEAN        ThisMinirdrIsTheWinner,
    IN OUT PVOID          pSrvCallContext);


extern NTSTATUS
HwFsQueryFileInformation(
    IN OUT PRX_CONTEXT      RxContext);

extern NTSTATUS
HwFsQueryNamedPipeInformation(
    IN OUT PRX_CONTEXT        RxContext,
    IN     FILE_INFORMATION_CLASS FileInformationClass,
    IN OUT PVOID              Buffer,
    IN OUT PULONG             pLengthRemaining);

extern NTSTATUS
HwFsSetFileInformation(
    IN OUT PRX_CONTEXT        RxContext);

extern NTSTATUS
HwFsSetNamedPipeInformation(
    IN OUT PRX_CONTEXT        RxContext,
    IN     FILE_INFORMATION_CLASS FileInformationClass,
    IN     PVOID              pBuffer,
    IN     ULONG              BufferLength);

NTSTATUS
HwFsSetFileInformationAtCleanup(
    IN OUT PRX_CONTEXT      RxContext
    );

NTSTATUS
HwFsDeallocateForFcb(
    IN OUT PMRX_FCB pFcb);

NTSTATUS
HwFsDeallocateForFobx(
    IN OUT PMRX_FOBX pFobx);

extern NTSTATUS
HwFsForcedClose(
    IN OUT PMRX_SRV_OPEN SrvOpen);

extern ULONG
HwFsExtendFile(
    IN OUT struct _RX_CONTEXT *RxContext,
    IN OUT PLARGE_INTEGER     pNewFileSize,
    OUT    PLARGE_INTEGER     pNewAllocationSize);

extern NTSTATUS
HwFsTruncateFile(
    IN OUT PRX_CONTEXT RxContext);

extern NTSTATUS
HwFsCompleteBufferingStateChangeRequest(
    IN OUT PRX_CONTEXT RxContext,
    IN OUT PMRX_SRV_OPEN   SrvOpen,
    IN     PVOID       pContext);

VOID
FobxFreeTemplate(
    IN PHWFS_FOBX_EXTENSION    pFobxExt);

// Compare RootName with PatternName
BOOLEAN
CheckRootName(
    PWCHAR    pRootName,
    USHORT    RootNameLength,
    PWCHAR    pPatternName,
    USHORT    PatternNameLength);

#include "mrxprocs.h"   // crossreferenced routines
#include "hwfs_shared.h"
